using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Runtime.Serialization;

namespace Rapier.Kodachi.Shared
{
    [Serializable]
    public abstract class Action : ILookupItem
    {
        #region Properties
        public string Key
        {
            get { return _Name + _ActionType + (_Plugin == null ? "Internal" : _Plugin.Guid.ToString()); }
        }

        private Plugin _Plugin;
        public Plugin Plugin
        {
            get { return _Plugin; }
            set { _Plugin = value; }
        }

        private string _Name;
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        private string _Description;
        public string Description
        {
            get { return _Description; }
            set { _Description = value; }
        }

        private string _ActionType;
        public string ActionType
        {
            get { return _ActionType; }
            set { _ActionType = value; }
        }

        public Bitmap Image
        {
            get
            {
                if (_GetImage != null)
                    return _GetImage();
                else
                    return null;
            }
        }

        private GetImageDelegate _GetImage = null;
        public GetImageDelegate GetImage
        {
            get { return _GetImage; }
            set { _GetImage = value; }
        }

        private IndirectItemUse _IndirectItemUse = IndirectItemUse.None;
        /// <summary>
        /// Does this action work with Indirect Items?
        /// </summary>
        public IndirectItemUse IndirectItemUse
        {
            get { return _IndirectItemUse; }
            set { _IndirectItemUse = value; }
        }

        public int MatchCount
        {
            get { return _QueryMatchCount[String.Empty]; }
            set { _QueryMatchCount[String.Empty] = value; }
        }

        private Dictionary<string, int> _QueryMatchCount = new Dictionary<string, int>();
        public Dictionary<string, int> QueryMatchCount
        {
            get { return _QueryMatchCount; }
            set { _QueryMatchCount = value; }
        }

        private bool _DefaultIndirectTextMode;
        public bool DefaultIndirectTextMode
        {
            get { return _DefaultIndirectTextMode; }
            set { _DefaultIndirectTextMode = value; }
        }
        #endregion

        #region Constructors
        public Action(Plugin plugin, string actionType)
        {
            _QueryMatchCount.Add(String.Empty, 0);
            _Plugin = plugin;
            _ActionType = actionType;
            _GetImage = delegate() { return Resource.DefaultAction; };
        }

        public Action(Plugin plugin, string actionType, string name) : this(plugin, actionType)
        {
            _Name = name;
        }

        public Action(Plugin plugin, string actionType, string name, string description) : this(plugin, actionType, name)
        {
            _Description = description;
        }
        #endregion

        #region Overrides
        /// <summary>
        /// Is this Action valid for the given Direct Item?
        /// </summary>
        /// <param name="directItem">Direct Item used to test validity</param>
        /// <returns>true if Action is valid for given Direct Item</returns>
        public abstract bool IsValidDirect(Item directItem);
        
        /// <summary>
        /// Is this Action valid for the given Indirect Item?
        /// </summary>
        /// <param name="indirectItem">Indirect Item used to test validity</param>
        /// <returns>true if Action is valid for given Indirect Item</returns>
        public virtual bool IsValidIndirect(Item indirectItem)
        {
            return false;
        }
        
        /// <summary>
        /// Execution of your action.
        /// </summary>
        /// <param name="directItems">Direct Items to execute on</param>
        /// <param name="indirectItems">Indirect Items to execute with</param>
        public abstract void Execute(Item[] directItems, Item[] indirectItems);

        public override bool Equals(object obj)
        {
            if (!typeof(Action).IsAssignableFrom(obj.GetType()))
                throw new ArgumentException("obj must be of type Action");

            return (_Name == (obj as Action)._Name && _Plugin.Guid == (obj as Action).Plugin.Guid);
        }

        public override int GetHashCode()
        {
            return Key.GetHashCode();
        }
        #endregion
    }

    public enum IndirectItemUse
    {
        None,
        Optional,
        Required
    }
}
